﻿#include "TcpSocket.h"                  // 头文件：类声明与跨平台宏等
#include <iostream>                     // 标准输入输出
#include <cstring>                      // C 字符串/内存操作（如 memset 等，这里未直接使用）
#include <chrono>                       // 时间/时钟工具（用于 sleep 的时间单位）
#include <thread>                       // 线程支持

#ifdef _WIN32                           // ---------- Windows 专用初始化 ----------
bool TcpSocket::wsa_initialized = false; // 静态标志：记录 WSA 是否初始化
void TcpSocket::initWSA() {
    if (!wsa_initialized) {             // 仅初始化一次
        WSADATA wsaData;                // 保存 WSA 启动返回的信息
        WSAStartup(MAKEWORD(2,2), &wsaData); // 启动 WinSock 2.2
        wsa_initialized = true;         // 置位：已初始化
    }
}
#endif

TcpSocket::TcpSocket() : main_fd(-1), connected(false), running(false) { // 构造：默认无套接字、未连接、未运行
#ifdef _WIN32
    initWSA();                          // Windows 下确保已调用 WSAStartup
#endif
}

TcpSocket::~TcpSocket() {               // 析构：收尾清理
    stopAsyncRecv();                    // 停止异步接收线程（若存在）
    stopServer();                       // 关闭服务端监听与所有客户端（若处于服务端模式）
#ifdef _WIN32
    WSACleanup();                       // Windows 下对应的 WinSock 清理
#endif
}

// ---------------- 客户端 ----------------
bool TcpSocket::connectServer(const std::string& ip, int port, int timeout_seconds) { // 连接到指定 IP:port；注意：参数 timeout_seconds 当前未生效
    main_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建 TCP 套接字
    if (main_fd < 0) return false;             // 创建失败直接返回

    sockaddr_in serv_addr{};                   // 服务器地址结构体（清零初始化）
    serv_addr.sin_family = AF_INET;            // IPv4
    serv_addr.sin_port = htons(port);          // 端口号：主机序转网络序
    inet_pton(AF_INET, ip.c_str(), &serv_addr.sin_addr); // 将点分十进制 IP 转成二进制网络字节序

    if (::connect(main_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) { // 发起阻塞式连接
        std::cerr << "Connect failed\n";      // 失败输出日志
        return false;                         // 返回失败
    }

    connected = true;                         // 标记：已建立客户端连接
    running = true;                           // 标记：运行中（用于控制循环）
    return true;                              // 连接成功
}

bool TcpSocket::sendData(const std::vector<char>& data) { // 客户端同步发送
    if (!connected) return false;             // 未连接则不能发送
    std::lock_guard<std::mutex> lock(send_mutex); // 发送加锁，避免并发写同一 fd
    size_t total_sent = 0;                    // 已发送字节计数
    while (total_sent < data.size()) {        // 循环直到全部发完
#ifdef _WIN32
        int n = ::send(main_fd, data.data() + total_sent, static_cast<int>(data.size() - total_sent), 0); // Windows 的 send
#else
        int n = ::send(main_fd, data.data() + total_sent, data.size() - total_sent, 0); // POSIX 的 send
#endif
        if (n <= 0) return false;             // 出错或对端关闭，发送失败
        total_sent += static_cast<size_t>(n); // 累加本次发送的字节数
    }
    return true;                              // 全部发送成功
}

void TcpSocket::sendDataAsync(const std::vector<char>& data) { // 客户端异步发送（后台线程）
    std::thread([this, data]{ sendData(data); }).detach(); // 启动临时线程调用同步发送；detach 分离线程
}

// ---------------- 服务端 ----------------
bool TcpSocket::startServer(int port) {       // 启动服务端监听
    main_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建监听套接字
    if (main_fd < 0) return false;            // 创建失败

    sockaddr_in addr{};                       // 绑定地址（清零）
    addr.sin_family = AF_INET;                // IPv4
    addr.sin_port = htons(port);              // 监听端口
    addr.sin_addr.s_addr = INADDR_ANY;        // 绑定到本机所有网卡

    if (bind(main_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) return false; // 绑定失败
    if (listen(main_fd, 5) < 0) return false; // 开始监听，backlog=5

    running = true;                            // 标记服务器运行中
    accept_thread = std::thread(&TcpSocket::acceptLoop, this); // 开启专用线程处理 accept()
    return true;                               // 启动成功
}

void TcpSocket::stopServer() {                 // 停止服务端（可重复调用，注意幂等）
    running = false;                           // 通知各循环尽快退出
    if (main_fd >= 0) {                        // 若监听 fd 有效
#ifdef _WIN32
        closesocket(main_fd);                  // Windows 关闭套接字
#else
        close(main_fd);                        // POSIX 关闭套接字
#endif
        main_fd = -1;                          // 置为无效
    }
    if (accept_thread.joinable()) accept_thread.join(); // 等待 accept 线程退出

    std::lock_guard<std::mutex> lock(fds_mutex); // 加锁后关闭所有已连接客户端
    for (auto fd : client_fds) {
#ifdef _WIN32
        closesocket(fd);                       // 逐个关闭客户端连接
#else
        close(fd);
#endif
    }
    client_fds.clear();                        // 清空客户端列表
}

// 服务端发送
bool TcpSocket::sendData(int client_fd, const std::vector<char>& data) { // 指定客户端 fd 的同步发送
    std::lock_guard<std::mutex> lock(send_mutex); // 与其他发送串行化
    size_t total_sent = 0;                    // 已发送计数
    while (total_sent < data.size()) {        // 保证全部发出
#ifdef _WIN32
        int n = ::send(client_fd, data.data() + total_sent, static_cast<int>(data.size() - total_sent), 0); // WinAPI
#else
        int n = ::send(client_fd, data.data() + total_sent, data.size() - total_sent, 0); // POSIX
#endif
        if (n <= 0) return false;             // 出错/断开
        total_sent += static_cast<size_t>(n); // 累加发送量
    }
    return true;                              // 发送完成
}

void TcpSocket::sendDataAsync(int client_fd, const std::vector<char>& data) { // 服务端异步发送
    std::thread([this, client_fd, data]{ sendData(client_fd, data); }).detach(); // 后台线程调用同步发送
}

// ---------------- 异步接收 ----------------
void TcpSocket::startAsyncRecv(RecvCallback callback) { // 启动异步接收：设置回调并起线程
    recv_callback = callback;                // 保存上层传入的回调
    recv_thread = std::thread(&TcpSocket::recvLoop, this); // 起一个“接收管理”线程（当前实现是占位/心跳）
}

void TcpSocket::stopAsyncRecv() {            // 停止异步接收线程
    if (recv_thread.joinable()) recv_thread.join(); // 若线程存在则等待退出
}

// ---------------- 内部函数 ----------------
void TcpSocket::acceptLoop() {               // 专用于服务端：持续接受新连接
    while (running) {                        // 只要处于运行状态就循环
#ifdef _WIN32
        int client_fd = ::accept(main_fd, nullptr, nullptr); // 接受新连接（阻塞）
#else
        int client_fd = ::accept(main_fd, nullptr, nullptr); // POSIX 接受（阻塞）
#endif
        if (client_fd >= 0) {                // 若有新客户端
            std::lock_guard<std::mutex> lock(fds_mutex); // 保护客户端列表
            client_fds.push_back(client_fd); // 保存新客户端 fd
            std::thread(&TcpSocket::handleClient, this, client_fd).detach(); // 为该客户端起独立处理线程
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 小憩，避免空转过快
    }
}

void TcpSocket::handleClient(int client_fd) { // 处理单个客户端的收发与生命周期
    char buffer[1024];                        // 临时接收缓冲区
    while (running) {                         // 服务端运行期间持续处理
#ifdef _WIN32
        int n = ::recv(client_fd, buffer, static_cast<int>(sizeof(buffer)), 0); // 从该客户端接收数据（阻塞）
#else
        int n = ::recv(client_fd, buffer, sizeof(buffer), 0); // POSIX 接收
#endif
        if (n <= 0) break;                    // 连接关闭或出错则退出循环

        if (recv_callback) {                  // 若上层注册了回调
            std::vector<char> data(buffer, buffer + n); // 将收到的数据复制到 vector
            recv_callback(client_fd, data);   // 回调给上层（线程上下文：本客户端线程）
        }

        // 回显：原样把收到的数据发回给该客户端（示例逻辑，可按需移除）
        ::send(client_fd, buffer, n, 0);      // 简单 echo，不做错误处理（生产中应检查返回值）
    }
#ifdef _WIN32
    closesocket(client_fd);                   // 退出前关闭该客户端连接
#else
    close(client_fd);
#endif
    std::lock_guard<std::mutex> lock(fds_mutex); // 从客户端列表移除该 fd
    client_fds.erase(std::remove(client_fds.begin(), client_fds.end(), client_fd), client_fds.end()); // 安全擦除
}

void TcpSocket::recvLoop() {                  // 接收管理线程（当前实现仅占位/维持生命周期）
    while (running || connected) {            // 只要服务端在跑或客户端处于已连接，就保持线程存活
        std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 轻量 sleep，避免忙等
        // 说明：真正的数据接收在 handleClient()（服务端）或用户自行扩展的客户端逻辑中完成
    }
}
